package com.tgpay.cdiot.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Service
public class UpstreamApiService {

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    @Value("${upstream.api.base-url:http://localhost:8980}")
    private String baseUrl;

    @Value("${upstream.api.app-secret:TgPay2024IoT9f8e7d6c5b4a3928f1e0d9c8b7a69584736251f0e9d8c7b6a5948372615}")
    private String appSecret;

    public UpstreamApiService(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }

    /**
     * 获取设备列表
     */
    public Object getDevices() {
        String url = baseUrl + "/tg/iot/api/devices";
        HttpHeaders headers = createSignedHeaders(new HashMap<>());
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class);
        return response.getBody();
    }

    /**
     * 获取设备详情
     */
    public Object getDeviceDetail(String imei) {
        String url = baseUrl + "/tg/iot/api/devices/" + imei;
        HttpHeaders headers = createSignedHeaders(new HashMap<>());
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class);
        return response.getBody();
    }

    /**
     * 启动充电
     */
    public Object startCharging(String imei, String portId, Map<String, Object> requestBody) {
        String url = baseUrl + "/tg/iot/api/devices/" + imei + "/ports/" + portId + "/start";
        
        try {
            String jsonBody = objectMapper.writeValueAsString(requestBody);
            HttpHeaders headers = createSignedHeaders(requestBody);
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);
            
            ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.POST, entity, Object.class);
            return response.getBody();
        } catch (Exception e) {
            throw new RuntimeException("启动充电失败: " + e.getMessage(), e);
        }
    }

    /**
     * 停止充电
     */
    public Object stopCharging(String imei, String portId, Map<String, Object> requestBody) {
        String url = baseUrl + "/tg/iot/api/devices/" + imei + "/ports/" + portId + "/stop";
        HttpHeaders headers = createSignedHeaders(requestBody != null ? requestBody : new HashMap<>());
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        String jsonBody = "";
        if (requestBody != null && !requestBody.isEmpty()) {
            try {
                jsonBody = objectMapper.writeValueAsString(requestBody);
            } catch (Exception e) {
                throw new RuntimeException("Failed to serialize request body", e);
            }
        }
        
        HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);
        ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.POST, entity, Object.class);
        return response.getBody();
    }

    /**
     * 获取充电状态
     */
    public Object getChargingStatus(String imei, String portId) {
        String url = baseUrl + "/tg/iot/api/devices/" + imei + "/status";
        HttpHeaders headers = createSignedHeaders(new HashMap<>());
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class);
        return response.getBody();
    }

    /**
     * 创建带签名的请求头
     */
    private HttpHeaders createSignedHeaders(Map<String, Object> params) {
        HttpHeaders headers = new HttpHeaders();
        long timestamp = System.currentTimeMillis();
        
        // 构建参数字符串
        Map<String, String> allParams = new TreeMap<>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            allParams.put(entry.getKey(), String.valueOf(entry.getValue()));
        }
        allParams.put("timestamp", String.valueOf(timestamp));
        
        // 构建签名字符串
        StringBuilder signString = new StringBuilder();
        for (Map.Entry<String, String> entry : allParams.entrySet()) {
            if (signString.length() > 0) {
                signString.append("&");
            }
            signString.append(entry.getKey()).append("=").append(entry.getValue());
        }
        
        // 生成签名
        String signature = generateSignature(signString.toString(), appSecret);
        
        headers.set("X-Signature", signature);
        headers.set("X-Timestamp", String.valueOf(timestamp));
        headers.set("Content-Type", "application/json");
        
        return headers;
    }

    /**
     * 生成HMAC-SHA256签名
     */
    private String generateSignature(String data, String secret) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            
            // 转换为小写十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("签名生成失败: " + e.getMessage(), e);
        }
    }
}